package luren.king.wechatlite.network;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;

import androidx.recyclerview.widget.RecyclerView;

import org.json.JSONException;
import org.json.JSONObject;

import java.text.MessageFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import luren.king.wechatlite.activity.MainActivity;
import luren.king.wechatlite.adapter.ChatAdapter;
import luren.king.wechatlite.adapter.MessageAdapter;
import luren.king.wechatlite.config.Config;
import luren.king.wechatlite.database.MessageDataBaseHelper;
import luren.king.wechatlite.database.MessageHelper;
import luren.king.wechatlite.pojo.ChatMessage;
import luren.king.wechatlite.pojo.Message;
import luren.king.wechatlite.utils.NotificationHelper;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

public class WebSocketClient {
    private static final String TAG = "彔忈-king";

    WebSocket socket;

    private RecyclerView recyclerView = Config.RECYCLER_VIEW;
    private ChatAdapter chatAdapter;
    private List<ChatMessage> chatMessageList;
    private Activity activity;
    private MessageAdapter messageAdapter;
    //这是主页的适配器
    private List<Message> messageList ;
    //这是主页的列表
    //现在要做的是，怎么知道哪个消息是哪个用户发送的？并且更新预览消息

    private MessageDataBaseHelper messageDataBaseHelper;
    private MessageHelper messageHelper;

    private String sender;


    // 心跳间隔，单位：秒
    private static final long RECONNECT_INTERVAL = 5; // 重新连接间隔，单位：秒
    private static final long HEARTBEAT_INTERVAL = 30; // 心跳间隔，单位：秒
    private static final long HEARTBEAT_TIMEOUT = 10; // 心跳超时时间，单位：秒
    private ScheduledExecutorService executorService;


    public void startWebsocket() {
        OkHttpClient client = new OkHttpClient
                .Builder()
                .pingInterval(10, TimeUnit.SECONDS) // 10秒发送一次心跳
                .build();
//        Request request = new Request.Builder().url("ws://luren-king.cn:8080/chat").build();
        Request request = new Request.Builder()
                .addHeader("token", Config.JWT_TOKEN)
                .url("ws://luren-king.cn:9090/chat")
                .build();
        webSocketListener listener = new webSocketListener();
        socket = client.newWebSocket(request, listener);
    }

    private void startHeartbeat() {
        // 创建一个单线程定时任务执行器
        executorService = Executors.newSingleThreadScheduledExecutor();
        // 定时执行发送心跳的任务，初始延迟为0秒，每次执行间隔为30秒
        executorService.scheduleWithFixedDelay(() -> {
            // 如果socket不为空
            if (socket != null) {
                // 发送心跳消息
                socket.send("heartbeat");

                // 设置心跳超时任务
                executorService.schedule(() -> {
                    // 如果socket不为空
                    if (socket != null) {
                        // 取消socket连接
                        socket.cancel();
                    }
                }, HEARTBEAT_TIMEOUT, TimeUnit.SECONDS);
            }
        }, 0, HEARTBEAT_INTERVAL, TimeUnit.SECONDS);
    }


    private void stopHeartbeat() {
        if (executorService != null) {
            executorService.shutdownNow();
        }
    }

    public void setSender(String sender){
        this.sender = sender;
    }

    public void setRecyclerView(RecyclerView recyclerView, ChatAdapter chatAdapter, List<ChatMessage> chatMessageList, Activity activity) {
        this.recyclerView = recyclerView;
        this.chatAdapter = chatAdapter;
        this.chatMessageList = chatMessageList;
        this.activity = activity;
    }

    public void setMainActInfo(MessageAdapter messageAdapter, List<Message> messageList) {
        this.messageAdapter = messageAdapter;
        this.messageList = messageList;
    }

    public void deleteRecyclerView() {
        this.recyclerView = null;
        this.chatAdapter = null;
        this.chatMessageList = null;
        this.activity = Config.MAIN_ACTIVITY;
    }

    private void addMessage(ChatMessage message) {
        chatMessageList.add(message);
        chatAdapter.notifyItemInserted(chatMessageList.size() - 1);
        recyclerView.scrollToPosition(chatMessageList.size() - 1);
    }

    public void closeWebSocket() {
        socket.close(1000, "再见!");
    }

    public void sendMessage(String message, String Email) {
        // 这里拿到消息并且要拿到发送的对象，然后拼接发送
        try
        {
            JSONObject msg = new JSONObject();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                msg.put("Email", Email);
                msg.put("message", message);
            }
            boolean send = socket.send(msg.toString());
            Log.d(TAG, "sendMessage: " + send);
            if (send) {
//                Message msg_ = new Message();
//                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//                    msg_.setTime(LocalDate.now().toString());
//                }
//                msg_.setName(Email);
//                msg_.setEmail(Email);
//                msg_.setMessage(message);
//                messageHelper.addOrUpdateMessage(msg_);
//                messageAdapter.notifyItemInserted(0);

                addMessage(new ChatMessage(message, ChatMessage.TYPE_SENT));
                messageDataBaseHelper = new MessageDataBaseHelper(activity);
                messageDataBaseHelper.insertMessage(Email, message, ChatMessage.TYPE_SENT);
                //将消息存入数据库中
            }
            else {
                Toast.makeText(activity, "发送失败,请重新启动", Toast.LENGTH_SHORT).show();
            }
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }

    }

    public void sendByteMessage(ByteString byteString) {
        socket.send(byteString);
    }

    private class webSocketListener extends WebSocketListener {
        @Override
        public void onOpen(WebSocket webSocket, Response response) {
            // 连接成功
            //startHeartbeat();
        }

        @SuppressLint("NotifyDataSetChanged")
        @Override
        public void onMessage(WebSocket webSocket, String text) {
            // 接收到消息,然后将消息解析并存进数据库并通知
            // todo 当接收到消息时，应该将消息存入到本地数据库中，并通知界面更新

            // todo 当接收到信息的时候，搜索邮箱是否是否已经存在于这里，存在就更新预览消息，不存在就添加一列
            try{
                messageHelper = new MessageHelper(activity);
                //这个是消息列表的数据库操作
                messageDataBaseHelper = new MessageDataBaseHelper(activity);
                // 这个是发送消息的数据库操作

                JSONObject message_a = new JSONObject(text);
                String message = message_a.getString("message");
                String Sender = message_a.getString("Email");

                messageDataBaseHelper.insertMessage(Sender, message, ChatMessage.TYPE_RECEIVED);
                //将消息存入数据库中

                if (activity.getClass() == MainActivity.class) {
                    //如果是主界面，则直接添加到聊天列表中
                    //messageList判断如果已经存在这个用户，则更新预览消息，否则添加到列表中，顺便这里会操作数据库
                    // 搜索sender是否存在
                    //messageAdapter适配器刷新页面
                    activity.runOnUiThread(() -> {
//                        Message msg = new Message();
//                        msg.setEmail(Sender);
//                        msg.setMessage(message);
//                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//                            msg.setTime(LocalDate.now().toString());
//                        }
//                        messageHelper.addOrUpdateMessage(msg);
//                        messageAdapter.notifyItemInserted(0);
                        //Toast.makeText(activity, "有新消息:"+text, Toast.LENGTH_SHORT).show();
                        NotificationHelper.sendNotification(activity, Sender, message);
                    });
                }
                else {
                    activity.runOnUiThread(() -> {
                        if (Sender.equals(sender)){
                            addMessage(new ChatMessage(message, ChatMessage.TYPE_RECEIVED));
                        }
                        else {
                            NotificationHelper.sendNotification(activity, Sender, message);
                        }
                    });
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void onClosed(WebSocket webSocket, int code, String reason) {
            // 当WebSocket连接关闭时调用此方法
            // 连接关闭
            //stopHeartbeat();
            // 关闭心跳
            //reconnect();
            // 重新连接
            activity.runOnUiThread(() -> {
                // 在UI线程中执行操作
                AlertDialog.Builder builder = new AlertDialog.Builder(activity);
                // 创建一个对话框构建器
                builder.setTitle("关闭连接了");
                // 设置对话框标题为"操作失败"
                builder.setMessage("这里有一个reson：" + reason + "\n这里还有一个code："+code);
                // 设置对话框消息，包含关闭原因和关闭代码
                builder.setPositiveButton("确定", (dialog, which) -> {
                    // 设置对话框的确定按钮点击事件
                    dialog.dismiss();
                    // 点击确定按钮后关闭对话框
                });
                builder.show();
            });
        }


        @Override
        public void onFailure(WebSocket webSocket, Throwable t, Response response) {
            // 连接失败
            String errorMessage = t.getClass().getName() + ": " + t.getMessage();
            StringBuilder sbException = new StringBuilder();
            sbException.append(errorMessage).append("\n");
            for (StackTraceElement ele : t.getStackTrace()) {
                sbException.append(MessageFormat.format("\tat {0}.{1}({2}:{3})\n",
                        ele.getClassName(), ele.getMethodName(), ele.getFileName(), ele.getLineNumber()));;
            }
            // 获取异常信息
            Log.d(TAG, "onFailure: " + sbException);
            // 打印异常信息

            //stopHeartbeat();
            // 关闭心跳
            //reconnect();
            // 重新连接
            activity.runOnUiThread(() -> {
                AlertDialog.Builder builder = new AlertDialog.Builder(activity);
                builder.setTitle("操作失败");
                builder.setMessage(sbException.toString());
                builder.setPositiveButton("确定", (dialog, which) -> {
                    dialog.dismiss();
                });
//                builder.show();
                // 先不弹窗报错了
            });


            startWebsocket();
            //重新连接
        }
    }

}
